//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_TIME_H__
#define __ELASTOS_TIME_H__

const uint_t c_uTickRate    = KCONFIG_TICKRATE;             // unit: herz
const uint_t c_uTickCycle   = 1000000000 / c_uTickRate;     // unit: ns

EXTERN uint_t g_uElapsedTicks;
EXTERN uint_t g_uLostTicks;

EXTERN uint_t DzGetElapsedTicks();
EXTERN uint_t DzGetIdleTicks();

EXTERN SystemTime g_systemTime;

EXTERN void DzSyncSystemTime();
EXTERN void DzGetSystemTime(SystemTime *pSystemTime);
EXTERN void DzSetSystemTime(SystemTime systemTime);
EXTERN ECode DzQueryPerformanceCounter(Int64 *pPerformanceCount);
EXTERN ECode DzQueryPerformanceFrequency(Int64 *pFrequency);

//
// Timer
//
typedef void (CDECL *timerroutine_t)(void *);

class DzTimer : public DLinkNode
{
    friend void CDECL HandleTimers();
    friend class SyncObject;
    friend class DzEvent;
    friend class DzEventSet;

public:
    DzTimer(timerroutine_t routine, void *pvParameter)
    {
        m_routine       = routine;
        m_pvParameter   = pvParameter;
        m_bCanceled     = TRUE;
    }

    void Set(uint_t uRelativeDueTicks)
    {
//        assert(uRelativeDueTicks > 0);
        m_uDueTicks = uRelativeDueTicks;
    }

    DzTimer(uint_t uRelativeDueTicks, timerroutine_t routine, void *pvParameter)
    {
        assert(uRelativeDueTicks > 0);
        m_uDueTicks     = uRelativeDueTicks;
        m_routine       = routine;
        m_pvParameter   = pvParameter;
        m_bCanceled     = TRUE;
    }

    void Start();

    void Restart(uint_t uRelativeDueTicks)
    {
        Set(uRelativeDueTicks);
        Start();
    }

    void Cancel();

    bool_t Due() const
    {
        return 0 == m_uDueTicks;
    }

    uint_t GetResidualTicks() const
    {
        assert(!Due());

        register uint_t uElapsedTicks = g_uElapsedTicks;
        return (m_uDueTicks <= uElapsedTicks)? 0 : m_uDueTicks - uElapsedTicks;
    }

private:
    void _Start();

private:
    uint_t          m_uDueTicks;
    Boolean         m_bCanceled;

    timerroutine_t  m_routine;
    void            *m_pvParameter;
};

INLINE uint_t DzMillisecondsToTicks(Millisecond32 milliseconds)
{
    const uint_t c_uTickDivisor = 1000 / c_uTickRate;

    return Max((uint_t)milliseconds, (uint_t)milliseconds + c_uTickDivisor - 1)
        / c_uTickDivisor;
}

INLINE Millisecond32 DzTicksToMilliseconds(uint_t ticks)
{
    return (Millisecond32)(ticks * (1000 / c_uTickRate));
}

#endif //__ELASTOS_TIME_H__
